package edu.gdut.thesissys.dao;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.LockMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import edu.gdut.thesissys.vo.BaseVo;

public class BaseDAO<T extends BaseVo> {
	private static final Logger log = LoggerFactory.getLogger(BaseDAO.class);

	@Resource
	private IHQLQuery hqlQuery;

	private Class<T> cls;
	private HibernateDaoSupport hibernateDaoSupport;

	public BaseDAO(Class<T> cls, HibernateDaoSupport hibernateDaoSupport) {
		super();
		this.cls = cls;
		this.hibernateDaoSupport = hibernateDaoSupport;
	}

	/**
	 * 将传入的对象状态设置为Transient状态
	 * 
	 * @param instance
	 *            对象
	 */
	public void attachClean(T instance) {
		log.debug("attaching clean " + instance.getClass().getName()
				+ " instance");
		try {
			hibernateDaoSupport.getHibernateTemplate().lock(instance,
					LockMode.NONE);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	/**
	 * 保存或者更新
	 * 
	 * @param instance
	 *            对象
	 */
	public void attachDirty(T instance) {
		log.debug("attaching dirty " + instance.getClass().getName()
				+ " instance");
		try {
			hibernateDaoSupport.getHibernateTemplate().saveOrUpdate(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	/**
	 * 删除
	 * 
	 * @param persistentInstance
	 *            持久化对象
	 */
	public void delete(T persistentInstance) {
		log.debug("deleting " + persistentInstance.getClass().getName()
				+ " instance");
		try {
			hibernateDaoSupport.getHibernateTemplate().delete(
					persistentInstance);
			log.debug("delete successful");
		} catch (RuntimeException re) {
			log.error("delete failed", re);
			throw re;
		}
	}

	/**
	 * 根据主键查询
	 * 
	 * @param id
	 *            主键值
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T findById(Serializable id) {
		log.debug("getting " + cls.getName() + " instance with id: " + id);
		try {
			return (T) hibernateDaoSupport.getHibernateTemplate().get(cls, id);
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw re;
		}
	}

	/**
	 * 将传入的detached状态的对象的属性复制到持久化对象中，并返回该持久化对象
	 * 
	 * @param detachedInstance
	 *            detached状态对象
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T merge(T detachedInstance) {
		log.debug("merging " + detachedInstance.getClass().getName()
				+ " instance");
		try {
			T result = (T) hibernateDaoSupport.getHibernateTemplate().merge(
					detachedInstance);
			log.debug("merge successful");
			return result;
		} catch (RuntimeException re) {
			log.error("merge failed", re);
			throw re;
		}
	}

	/**
	 * 保存
	 * 
	 * @param transientInstance
	 *            瞬息对象
	 */
	public void save(T transientInstance) {
		log.debug("saving " + transientInstance.getClass().getName()
				+ " instance");
		try {
			hibernateDaoSupport.getHibernateTemplate().save(transientInstance);
			log.debug("save successful");
		} catch (RuntimeException re) {
			log.error("save failed", re);
			throw re;
		}
	}

	/**
	 * 根据属性值查询
	 * 
	 * @param propertyName
	 *            属性名
	 * @param value
	 *            属性值
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String propertyName, Object value) {
		log.debug("finding " + cls.getName() + " instance with property: "
				+ propertyName + ", value: " + value);
		try {
			String queryString = "from " + cls.getName()
					+ " as model where model." + propertyName + "= ?";
			return hibernateDaoSupport.getHibernateTemplate().find(queryString,
					value);
		} catch (RuntimeException re) {
			log.error("find by property name failed", re);
			throw re;
		}
	}

	/**
	 * 查询全部
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		log.debug("finding all " + cls.getName() + " instances");
		try {
			String queryString = "from " + cls.getName();
			return hibernateDaoSupport.getHibernateTemplate().find(queryString);
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}

	/**
	 * 查找全部，查找顺序随机
	 * 
	 * @param offset
	 *            开始位置
	 * @param pagesize
	 *            查找记录数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll(int offset, int pagesize) {
		log.debug("finding all " + cls.getName() + " instances");
		try {
			String queryString = "from " + cls.getName();
			return hqlQuery.find(queryString, offset, pagesize);
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}

	/**
	 * 统计记录总数
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public int countRow() {
		log.debug("count all rows of " + cls.getName());
		try {
			String queryString = "select count(*) from " + cls.getName();
			List result = hibernateDaoSupport.getHibernateTemplate().find(
					queryString);
			if (!result.isEmpty()) {
				log.debug("count successful and the value is "
						+ ((Long) result.get(0)).intValue());
				return ((Long) result.get(0)).intValue();
			}
			return 0;
		} catch (DataAccessException e) {
			log.error("count failed", e);
			throw e;
		}
	}

}
